package com.abacus.salary.dao;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Restrictions;

import com.abacus.salary.model.ItemGroupValue;
import com.abacus.salary.model.ItemValue;
import com.abacus.salary.model.Value;

public class DaoHelper {
	Session session;

	public DaoHelper() {
		super();
		session = SessionProvider.getCurrentSession();
	}

	protected Session getSession() {
		return session;
	}

	@SuppressWarnings("unchecked")
	public <T> T persistByExample(T value, Map<String, Object> params, String... excludePropertys) {
		if (null == value) {
			return null;
		}
		Criteria criteria = this.getSession().createCriteria(value.getClass());
		Example example = Example.create(value);
		if (null != excludePropertys && excludePropertys.length > 0) {
			for (String name : excludePropertys) {
				example.excludeProperty(name);
			}
		}
		criteria.add(example);
		buildParameter(criteria, params);
		Object uniqueResult = criteria.uniqueResult();
		if (null == uniqueResult) {
			this.getSession().save(value);
		} else {
			value = (T) uniqueResult;
		}
		return value;
	}

	protected void buildParameter(Criteria criteria, Map<String, Object> params) {
		if (null != params) {
			Object v;
			for (Entry<String, Object> e : params.entrySet()) {
				v = e.getValue();
				if (null == v) {
					criteria.add(Restrictions.isNull(e.getKey()));
				} else if (Collection.class.isAssignableFrom(v.getClass())) {
					criteria.add(Restrictions.in(e.getKey(), (Collection<?>) v));
				} else if (v.getClass().isArray()) {
					criteria.add(Restrictions.in(e.getKey(), (Object[]) v));
				} else {
					criteria.add(Restrictions.eq(e.getKey(), v));
				}
			}
		}
	}

	public ItemValue saveOrUpdateByExample(ItemValue itemValue) {
		if (null == itemValue) {
			return null;
		}
		if (null == itemValue.getItem() || null == itemValue.getItem().getName()) {
			throw new IllegalArgumentException("the item = null");
		}
		if (null == itemValue.getValue() || null == itemValue.getValue().value()) {
			throw new IllegalArgumentException("the value = null");
		}
		itemValue.setItem(this.persistByExample(itemValue.getItem(), null));
		Value value = this.persistByExample(itemValue.getValue(), null);
		itemValue.setValue(null);
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("item.id", itemValue.getItem().getId());
		itemValue = this.persistByExample(itemValue, params);
		itemValue.setValue(value);
		this.getSession().update(itemValue);
		return itemValue;
	}

	public ItemGroupValue saveOrUpdateByExample(ItemGroupValue itemGroupValue) {
		if (null == itemGroupValue) {
			return null;
		}
		if (null == itemGroupValue.getName()) {
			throw new IllegalArgumentException("the item = null");
		}
		if (null == itemGroupValue.getItem() || null == itemGroupValue.getItem().getName()) {
			throw new IllegalArgumentException("the item = null");
		}
		if (null == itemGroupValue.getValue() || null == itemGroupValue.getValue().value()) {
			throw new IllegalArgumentException("the value = null");
		}
		itemGroupValue.setItem(this.persistByExample(itemGroupValue.getItem(), null));
		itemGroupValue.setValue(this.persistByExample(itemGroupValue.getValue(), null));
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("item.id", itemGroupValue.getItem().getId());
		params.put("value.id", itemGroupValue.getValue().getId());
		itemGroupValue = this.persistByExample(itemGroupValue, params);
		return itemGroupValue;
	}
}
